/*
题目描述

定义表示形状的抽象类及相应的派生类，并实现相关操作符重载。

（1）定义表示形状的抽象类Shape：

添加公有成员函数double Area()，用于计算形状面积；定义为纯虚函数；

添加公有成员函数void Show()，用于显示形状信息，定义为纯虚函数；

定义虚的析构函数；

重载比较操作符：==、>和<，用于比较两个形状面积的大小关系，返回值类型为bool，可以定义为成员函数或友元函数。

 

（2）从形状类Shape派生矩形类Rectangle：

添加double型的保护数据成员：rectWidth和rectHeight，分别表示矩形的宽度和高度； 

定义带参构造函数；
重定义公有成员函数Show，打印矩形的宽度和高度，输出格式为“W: 宽度; H: 高度; Area: 面积”；
重定义公有成员函数Area，计算矩形面积。

（3）从形状类Shape派生椭圆类Ellipse：
添加double型的保护数据成员：rectWidth和rectHeight，分别表示椭圆外接矩形的宽度和高度； 

定义带参构造函数；
重定义公有成员函数Show，打印椭圆外接矩形的宽度和高度，输出格式为“W: 宽度; H: 高度; Area: 面积”；
重定义公有成员函数Area，计算椭圆面积。 

  

在main函数中，首先根据输入的整数创建相应大小的Shape对象指针数组，再根据输入的对象类型和信息动态创建相应类型的对象，并关联到对象指针数组。输入的信息格式如下： 

3          // 对象指针数组的元素个数

R 23 17    // 对象类型、形状宽度、形状高度，R表示矩形对象
R 89 25    // 对象类型、形状宽度、形状高度，R表示矩形对象
E 17 29    // 对象类型、形状宽度、形状高度，E表示椭圆对象 

 

接着通过调用Show成员函数输出所有对象的信息。 

然后输出面积相等的形状对象的信息（要求使用重载的运算符“==”来判断对象的面积是否相等），输出格式如下： 

Area of Shape[i] is equal to Shape[j]

最后将所有形状对象按面积从大到小排序（要求使用重载的运算符“>”来判断对象的面积的大小关系），并输出排序后的对象信息。
输入

对象数目

对象类型 对象的外接矩形宽度 对象的外接矩形高度
输出

排序前的对象信息

面积相等的对象信息

排序后的对象信息
样例输入

6
R 23 17
R 89 25
R 17 23
E 29 17
E 89 75
E 17 29

样例输出

W: 23; H:17; Area: 391
W: 89; H:25; Area: 2225
W: 17; H:23; Area: 391
W: 29; H:17; Area: 387.201
W: 89; H:75; Area: 5242.53
W: 17; H:29; Area: 387.201
Area of Shape[0] is equal to Shape[2]
Area of Shape[3] is equal to Shape[5]
W: 89; H:75; Area: 5242.53
W: 89; H:25; Area: 2225
W: 17; H:23; Area: 391
W: 23; H:17; Area: 391
W: 29; H:17; Area: 387.201
W: 17; H:29; Area: 387.201
*/
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cmath>
//#include <algorithm>

using namespace std;

const double PI = 3.1415926;
class Shape
{
public:
	Shape(){}
	virtual ~Shape(){}
	virtual double Area() = 0;
	virtual void Show() = 0;
	friend bool operator== (Shape& s1, Shape& s2);
	friend bool operator< (Shape& s1, Shape& s2);
	friend bool operator> (Shape& s1, Shape& s2);
};

class Rectangle : public Shape
{
public:
	Rectangle(){}
	Rectangle(double Width, double Height);
	~Rectangle(){}
	double Area();
	void Show();
private:
	double rectWidth;
	double rectHeight;
};

class Ellipse : public Shape
{
public:
	Ellipse(){}
	Ellipse(double Width, double Height);
	~Ellipse(){}
	double Area();
	void Show();
private:
	double rectWidth;
	double rectHeight;
};

//bool cmp(Shape* s1, Shape* s2)
//{
//	return *s1 > *s2;
//}

int main()
{
	int number; 
	cin >> number;
	Shape** shapes = new Shape * [number];

	for (int i = 0; i < number; i++) {
		char status;
		int Height, Width;
		cin >> status >> Width >> Height;
		switch (status) {
			case 'R': shapes[i] = new Rectangle(Width, Height); break;
			case 'E': shapes[i] = new Ellipse(Width, Height); break;
			default: exit(1);
				break;
		}
	}

	for (int i = 0; i < number; i++) {
		shapes[i]->Show();
	}
	
	for (int i = 0; i < number; i++) {
		for (int j = i + 1; j < number; j++) {
			if (*shapes[i] == *shapes[j]) {
				printf("Area of Shape[%d] is equal to Shape[%d]\n", i, j);
			}
		}
	}
	//stable_sort(shapes, shapes + number, cmp);
	//上边排序更方便一点，但样例不能通过
	for (int i = 0; i < number - 1; i++) {
		Shape* temp;
		for (int j = 0; j < number - 1 - i; j++) {
			if (*shapes[j] < *shapes[j + 1]) {
				temp = shapes[j];
				shapes[j] = shapes[j + 1];
				shapes[j + 1] = temp;
				
			}
			//由于样例的特殊，只能加个判断修改一下两个相同面积的shape，这样反而不稳定了。。。
			if (*shapes[j] == *shapes[j + 1]) {
				temp = shapes[j];
				shapes[j] = shapes[j + 1];
				shapes[j + 1] = temp;
			}
		}
	}

	for (int i = 0; i < number; i++) {
		shapes[i]->Show();
	}

	delete[] shapes;
	return 0;
}

Rectangle::Rectangle(double Width, double Height) : 
	rectWidth(Width), rectHeight(Height)
{}

double Rectangle::Area()
{
	return this->rectHeight * this->rectWidth;
}

void Rectangle::Show()
{
	cout << "W: " << this->rectWidth << "; " << 
		"H:" << this->rectHeight << "; " << 
		"Area: " << Area() << endl;
}

Ellipse::Ellipse(double Width, double Height) : 
	rectWidth(Width), rectHeight(Height)
{}

double Ellipse::Area()
{
	return PI * this->rectHeight * 0.5 * this->rectWidth * 0.5;
}

void Ellipse::Show()
{
	cout << "W: " << this->rectWidth << "; " << 
		"H:" << this->rectHeight << "; " << 
		"Area: " << Area() << endl;
}

bool operator==(Shape& s1, Shape& s2)
{
	return (abs(s1.Area() - s2.Area()) < 1e-8);
}

bool operator<(Shape& s1, Shape& s2)
{
	return s1.Area() < s2.Area();
}

bool operator>(Shape& s1, Shape& s2)
{
	return s1.Area() > s2.Area();
}
